package com.zx.crowdfunding.security;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.Assert;

/**
 * <p>自定义的SpringSecurity权限属性<p>
 * 为了在自定义的投票者里能够使用SPEL表达式判断权限，而模仿WebExpressionConfigAttribute这个类</br>
 * 因为WebExpressionConfigAttribute这个类不能在外部使用</br>
 * 为了实现动态权限控制，不用在Controller的方法上加注解，解决了硬编码的问题
 * @author 郑雪
 * @date 2021-12-16
 */
public class CrowdFundingConfigAttribute implements ConfigAttribute {

	private static final long serialVersionUID = 1L;

	private final Expression filterExpression;
	private final Expression authorizeExpression;
	private final String filterTarget;
	
	public CrowdFundingConfigAttribute(String filterExpression, String filterTarget,
			String authorizeExpression) {
		Assert.isTrue(filterExpression != null || authorizeExpression != null,
				"Filter and authorization Expressions cannot both be null");
		SpelExpressionParser parser = new SpelExpressionParser();
		this.filterExpression = filterExpression == null ? null : parser
				.parseExpression(filterExpression);
		this.authorizeExpression = authorizeExpression == null ? null : parser
				.parseExpression(authorizeExpression);
		this.filterTarget = filterTarget;
	}

	public CrowdFundingConfigAttribute(Expression filterExpression, String filterTarget
			,Expression authorizeExpression) {
		Assert.isTrue(filterExpression != null || authorizeExpression != null,
				"Filter and authorization Expressions cannot both be null");
		this.filterExpression = filterExpression == null ? null : filterExpression;
		this.authorizeExpression = authorizeExpression == null ? null
				: authorizeExpression;
		this.filterTarget = filterTarget;
	}
	
	public EvaluationContext postProcess(EvaluationContext context, FilterInvocation fi) {
		return context;
	}
	
	/**
	 * The parameter name of the target argument (must be a Collection) to which filtering
	 * will be applied.
	 *
	 * @return the method parameter name
	 */
	String getFilterTarget() {
		return filterTarget;
	}
	
	Expression getFilterExpression() {
		return filterExpression;
	}

	Expression getAuthorizeExpression() {
		return authorizeExpression;
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		Expression authorize = getAuthorizeExpression();
		Expression filter = getFilterExpression();
		sb.append("[authorize: '").append(
				authorize == null ? "null" : authorize.getExpressionString());
		sb.append("', filter: '").append(
				filter == null ? "null" : filter.getExpressionString());
		sb.append("', filterTarget: '").append(filterTarget).append("']");
		return sb.toString();
	}

	@Override
	public String getAttribute() {
		return null;
	}

}
